<?php
/**
 * Local Disk File System.
 * @package safsi_localdisk
 */

require_once('safsi_Util.php');
require_once('safsi_IFileSystem.php');
require_once('safsi_localdisk_Container.php');
require_once('safsi_localdisk_Util.php');

/**
 * Local Disk File System.
 * @package safsi_localdisk
 */
class safsi_localdisk_FileSystem implements safsi_IFileSystem {

    /**
     * Root path for the file system.
     * @var string
     */
    private $root;

    /**
     * Create a new Local Disk File System.
     * @param string $root Root path for the file system
     */
    public function __construct($root) {
        $this->root = $root;
    }

    /**
     * Creates a safsi_IContainer.
     * @param mixed $container Name of container or a safsi_IContainer instance
     * @return safsi_IContainer
     */
    public function createContainer($container) {

        $container = $this->getContainer($container);

        $this->mkDir(explode(DIRECTORY_SEPARATOR, $this->constructPath($container)));

        return $container;
    }

    /**
     * Deletes a safsi_IContainer.
     * @param mixed $container Name of container or a safsi_IContainer instance
     */
    public function deleteContainer($container) {
        if ( is_string($container) ) $container = $this->getContainer($container);
        $containerPath = $this->constructPath($container);
        $dh = dir($containerPath);
        $entry = null;
        while (false !== $entry = $dh->read()) {
            if ( $entry == '.' || $entry == '..' ) {
                continue;
            }
            throw new safsi_exception_ContainerNotEmptyException(
                $this,
                $container
            );
        }
        return safsi_localdisk_Util::RM_DIR($containerPath);
    }

    /**
     * Gets a safsi_IContainer.
     * @param string $container Name of container
     * @return safsi_IContainer
     */
    public function getContainer($container) {
        return new safsi_localdisk_Container($this, $container);
    }

    /**
     * Get the root path for the file system.
     * @return string Root path
     */
    public function root() {
        return $this->root;
    }

    public function constructPath(safsi_localdisk_Container $container = null, safsi_localdisk_Object $object = null) {
        $parts = explode(DIRECTORY_SEPARATOR, $this->constructPathToObject($container, $object));
        if ( $object !== null ) array_pop($parts);
        return implode(DIRECTORY_SEPARATOR, $parts);
    }

    public function constructPathToObject(safsi_localdisk_Container $container = null, safsi_localdisk_Object $object = null) {
        $parts = array(safsi_Util::TRIM_TRAILING($this->root()));
        if ( $container !== null ) $parts[] = $container->name();
        if ( $object !== null ) $parts[] = safsi_Util::TRIM_LEADING($object->name());
        return implode(DIRECTORY_SEPARATOR, $parts);
    }

    public function constructObjectFileName(safsi_localdisk_Object $object = null) {
        if ( $object === null ) return null;
        $parts = explode(DIRECTORY_SEPARATOR, $object->name());
        return array_pop($parts);
    }

    public function mkDir($parts) {
        $pathSoFar = DIRECTORY_SEPARATOR . array_shift($parts);
        while ( $parts ) {
            $pathSoFar .= array_shift($parts);
            if ( ! file_exists($pathSoFar) ) {
                mkdir($pathSoFar);
            }
            $pathSoFar .= DIRECTORY_SEPARATOR;
        }
    }

}

?>
